import json
import time
from utils.utl_util import merge_url_params, get_request_header

import requests


def do_monitor(bili_ticket: str, project_id: str, buyer_info: list[str]) -> bool:
    query_data = {
        "id": project_id,
        "project_id": project_id,
        "requestSource": "neul-next"
    }
    link_url = merge_url_params("https://show.bilibili.com/api/ticket/project/getV2", query_data)
    response = requests.get(link_url, headers=get_request_header({"SESSDATA": bili_ticket}))
    response_json = response.json()
    current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print(f"[{current_time}] 监控余票中: ", response_json["data"]["name"])
    if response_json["code"] == 0:
        screen_list = response_json["data"]["screen_list"]
        for screen in screen_list:
            screen_id = screen["id"]
            ticket_list = screen["ticket_list"]
            for ticket in ticket_list:
                if ticket["clickable"]:
                    sku_id = ticket["id"]
                    ticket_name = ticket["desc"]
                    screen_name = ticket["screen_name"]

                    print(f"检测到 [{current_time}] 时间: {screen_name} 席位: {ticket_name} 有票, 开始抢票")

                    token_info = prepare_buy(bili_ticket, project_id, screen_id, sku_id)
                    order_info = confirm_order(bili_ticket, project_id, token_info)
                    return create_order(bili_ticket, token_info, buyer_info, order_info)
    return False


def confirm_order(bili_ticket: str, project_id: str, token_data: dict) -> dict:
    timestamp = int(round(time.time() * 1000))
    query_data = {
        **token_data,
        "project_id": project_id,
        "timestamp": timestamp,
        "requestSource": "neul-next"
    }
    link_url = merge_url_params("https://show.bilibili.com/api/ticket/order/confirmInfo", query_data)
    response_data = requests.get(link_url, headers=get_request_header({"SESSDATA": bili_ticket})).json()["data"]
    return {
        **response_data,
        "origin_timestamp": timestamp
    }


def prepare_buy(bili_ticket: str, project_id: str, screen_id: str, sku_id: str) -> dict:
    """
    获取购买请求参数
    :param bili_ticket: 请求token
    :param project_id: 项目ID
    :param screen_id: 演出ID
    :param sku_id: 商品ID
    :return: token和ptoken
    """
    link_url = f"https://show.bilibili.com/api/ticket/order/prepare?project_id={project_id}"
    data = {
        "project_id": project_id,
        "screen_id": screen_id,
        "order_type": 1,
        "count": 1,
        "sku_id": sku_id,
        "buyer_info": "1,2",
        "ignoreRequestLimit": True,
        "ticket_agent": "",
        "newRisk": True,
        "requestSource": "neul-next"
    }
    response = requests.post(link_url, json=data, headers=get_request_header({"SESSDATA": bili_ticket}))
    response_data = response.json()["data"]
    return {
        "token": response_data["token"],
        "ptoken": response_data["ptoken"]
    }


def create_order(bili_ticket: str, token_data: dict, buyer_info: list[str], order_info: dict):
    """
    创建订单
    :param bili_ticket: cookie
    :param token_data: prepare_buy返回的token和ptoken
    :param buyer_info: 买家信息
    :param order_info: 商品信息
    :return:
    """
    query_data = {
        "ptoken": token_data["ptoken"],
        "project_id": order_info["project_id"],
        "requestSource": "neul-next"
    }
    buyer_info_data = []
    for buyer_data in order_info['buyerList']['list']:
        if str(buyer_data['id']) in buyer_info:
            buyer_info_data.append(buyer_data)

    link_url = merge_url_params(order_info["orderCreateUrl"], query_data)
    again = 0
    while True:
        print("下单尝试次数: ", again + 1)
        timestamp = int(round(time.time() * 1000))
        data = {
            **token_data,
            "pay_money": order_info["pay_money"],
            "buyer_info": json.dumps(buyer_info_data),
            "project_id": order_info["project_id"],
            "screen_id": order_info["screen_id"],
            "order_type": order_info["order_type"],
            "count": 1,
            "sku_id": order_info["ticket_info"]["sku_id"],
            "timestamp": timestamp,
            "again": again,
            "deviceId": "4cd16f1a1f890eeffc90b335ad7d86d6",
            "orderCreateUrl": order_info["orderCreateUrl"],
            "requestSource": "neul-next",
        }
        # print("RequestData:", data)
        response = requests.post(link_url, json=data, headers=get_request_header({"SESSDATA": bili_ticket}))
        if response.status_code != 200:
            print("请求失败, 状态码: ", response.status_code)
            continue
        response_data = response.json()
        print(response.status_code, response_data)
        errno = response_data["errno"]
        if errno == 0:
            print("下单成功, 请尽快支付!")
            return True
        elif errno == 900001 or errno == 900002:
            again += 1
            time.sleep(0.3)
        else:
            print("抢票失败, 准备重新监控余票")
            return False


if __name__ == '__main__':
    print("开始监控")
    token = ""

    while True:
        if do_monitor(token, "102626", ['2556327']):
            break
        time.sleep(1)

